package com.xiaojiezhu.netty.base.demo.timer;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.Date;

/**
 * 作者 zxj<br>
 * 时间 2017/7/14 12:52
 * 说明 这里构建一个了一个内部可积累的缓冲，直到4个字节全部进入了缓冲区
 *
 * 尽管第一个解决方案已经解决了 TIME 客户端的问题了，但是修改后的处理器看起来不那么的简洁，想象一下如
 * 果由多个字段比如可变长度的字段组成的更为复杂的协议时，你的 ChannelInboundHandler 的实现将很快地变
 * 得难以维护，因为长度是不确定的
 *
 * 请参见 TimerClientHandler3 包中的类
 */
public class TimerClientHandler2 extends ChannelInboundHandlerAdapter {
    private ByteBuf buf;

    /**
     * 连接被加入，创建一个可以积累的缓冲区
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        buf = ctx.alloc().buffer(4);
    }

    /**
     * 连接被移除,此时释放资源
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        buf.release();
        buf = null;
    }

    /**
     * 读取消息
     * @param ctx
     * @param msg
     * @throws Exception
     * 然后，处理器必须检查 buf 变量是否有足够的数据，在这个例子中是4个字节，然后处理实际的业务逻辑。否
    则，Netty 会重复调用channelRead() 当有更多数据到达直到4个字节的数据被积累
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf m = (ByteBuf) msg;
        buf.writeBytes(m);//每当接收到一个字节时，给缓冲起来，
        m.release();//缓冲到另一个字节中时，释放掉接收的资源
        if(buf.readableBytes() >= 4){
            long currentTimeMillis = (buf.readUnsignedInt() - 2208988800L) * 1000L;
            System.out.println(new Date(currentTimeMillis).toLocaleString());
            ctx.close();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        cause.printStackTrace();
        ctx.close();
    }
}
